using System;
using System.Net;
using System.Collections;
using System.Threading;
using log4net;
using log4net.Config;
using Whitemice.MOGI;
using Whitemice.MOGI.RPC2;

namespace Whitemice.MOGI.MOGIMon
{
	/// \brief MOGIMon service class
	public class MOGIMon : System.ServiceProcess.ServiceBase
	{
		private System.Timers.Timer 	timer;
		private	IServer					server;
		private	Auditor					auditor;
		private	RecordKeeper			keeper;
		private	Worker					worker;
		private static ILog				log;
		
		/// \brief Entry point
		public static void Main()
		{
			log = LogManager.GetLogger("MOGIMon");
			//log.Logger = 
			MOGIMon mon = new MOGIMon();
			log.Debug("MOGIMon Log Openned");
			System.ServiceProcess.ServiceBase[] services
				= new System.ServiceProcess.ServiceBase[] { mon };
			log.Debug("About to run services");
			System.ServiceProcess.ServiceBase.Run(services);
			log.Debug("Services running.");
		}
	
		/// \brief Constructor
		public MOGIMon()
		{
			this.ServiceName = "MOGIMon";
			InitializeComponents();
		}
	
		/// \brief Bootstrap
		private void InitializeComponents()
	    {
	    	log.Debug("Initializing components.");
			server = new Whitemice.MOGI.RPC2.Server();
			server.Hostname = server.GetDirectiveValue("MOGIMon", "Hostname");			
			server.Credentials = new NetworkCredential(
				server.GetDirectiveValue("MOGIMon", "Username"),
				server.GetDirectiveValue("MOGIMon", "Secret"));
			if (!server.Connected)
			{
				log.Fatal("Unable to connecto to groupware server");
				Thread.CurrentThread.Abort();
			}		
			log.Debug("Connected to back office.");
			keeper = new RecordKeeper(server);
			auditor = new Auditor(server, keeper);
			worker = new Worker(server, keeper);
			timer = new System.Timers.Timer(); 
     		timer.Elapsed += 
   				new System.Timers.ElapsedEventHandler(OnTimerElapsed);
   			log.Debug("Components initialized.");
		}
		
		protected override void Dispose(bool disposing)
		{
			log.Debug("Disposing...");
			timer.Stop();
			worker.Shutdown();
			auditor.Disconnect();
			keeper.Disconnect();		
			base.Dispose(disposing);
		}
		
		protected override void OnStart(string[] args)
		{
			log.Info("Starting service.");
			server.Hostname = server.GetDirectiveValue("MOGIMon", "Hostname");			
			server.Credentials = new NetworkCredential(
				server.GetDirectiveValue("MOGIMon", "Username"),
				server.GetDirectiveValue("MOGIMon", "Secret"));
			if(server.Connected)
			{
				log.Fatal("Unable to connecto to groupware server");
				Console.WriteLine("Unable to connect to groupware server");
				Thread.CurrentThread.Abort();
			}				
			log.Debug("Connected to back office");
			timer.Interval = Convert.ToDouble(server.GetDirectiveValue("MOGIMon", "LoopDelay"));
			log.Debug("Interval retrieved from configuration");
			keeper.Connect();
			log.Debug("Book keeper connected.");
			auditor.Connect();
			log.Debug("Auditor connected.");
			worker.Load();
			log.Debug("Workers loaded.");
			timer.Start();
			log.Debug("Timer started.");
		}
		
		protected override void OnStop()
		{
			log.Info("Stoping service.");
			timer.Stop();
			worker.Shutdown();
			auditor.Disconnect();
			keeper.Disconnect();
		}
		
		protected override void OnPause()
		{
			log.Info("Pausing service.");
			timer.Stop();
		}
		
		protected void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs args)
		{
			Hashtable 	changes;

			log.Debug("Invoking worker as result of timer tick.");
			changes = auditor.Changes;
			foreach(string documentName in changes.Keys)
				worker.Do((Change)changes[documentName]);		
		}
	}
}